Skip to content

Open on a class that does something, and fix loading an assignment - #24

Merged
matt-edmondson merged 3 commits into
mainfrom
claude/default-document-class
Sep 8, 2026
Merged

Open on a class that does something, and fix loading an assignment#24
matt-edmondson merged 3 commits into
mainfrom
claude/default-document-class

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Default document

The editor opened on a function with one parameter and an empty body. That shows neither what the node kinds are nor how they connect, which on a graph canvas is most of what a starting document is for.

NewDocument() now returns a small Counter class: two initialised fields, and two methods that use them — one assigning the result of a binary expression back to a field and returning it, one declaring a local from an expression and returning that. A field, a parameter, an assignment, a binary expression, a local and a return are all on screen at once.

Generated C#:

public class Counter
{
    int count = 0;
    int step = 1;
    public int Add(int amount)
    {
        count = (count + amount);
        return count;
    }
    public int Next()
    {
        int result = (count + step);
        return result;
    }
}

Python comes out equivalently (class Counter:, def Add(self, amount: int) -> int:), so the preview pane has something worth switching languages on.

NewClassDocument() is left alone — "New class" still gives a bare class to start from, which is a different thing from a worked example.

A bug this surfaced

The new document could not be reopened, and neither could any document containing an assignment.

AssignmentStatement's parameterless constructor — the one its own comment says is "Used for deserialization" — built its placeholder target with new VariableReference(""). That overload throws on an empty name:

System.ArgumentException: Name cannot be null or whitespace (Parameter 'name')
   at ktsu.Coder.Ast.VariableReference..ctor(String name)
   at ktsu.Coder.Ast.AssignmentStatement..ctor()
   at ktsu.Coder.Serialization.YamlDeserializer.DeserializeAssignmentStatement(...)

So YamlDeserializer threw before it could overwrite the placeholder and the load failed. It now uses the parameterless VariableReference, whose whole job is to leave the name empty. One line, and the only instance of the pattern in the codebase — I grepped.

This is pre-existing on main; it was simply never exercised, because nothing the editor produced by default had an assignment in it.

Testing

  • NewDocument_IsAClassWithFieldsAndMethodsThatDoSomething — replaces the old test that asserted a function with one parameter. Checks both fields are initialised, both methods have bodies, and that a method assigns an expression result and another declares a local from one.
  • Document_WithAnAssignment_RoundTripsThroughTheFileSystem — new, and fails without the constructor fix. This is the path a user takes by saving and reopening what the editor handed them.
  • Four existing tests that asserted against the old default (newFunction) updated to the new one: the round-trip, the language preview, and the export.

Coder.Test 330/330, full solution builds clean in Release.

Not verified visually — this environment is headless, so how the new document lays out on the canvas is worth a glance.

🤖 Generated with Claude Code

https://claude.ai/code/session_01D2KNUKr1xJPTEdDmeF2tQN


Generated by Claude Code

The editor opened on a function with one parameter and an empty body. That
shows neither what the node kinds are nor how they connect, which on a
graph canvas is most of what a starting document is for.

It now opens on a small Counter class: two initialised fields, and two
methods that use them - one assigning the result of a binary expression
back to a field and returning it, one declaring a local from an expression
and returning that. A field, a parameter, an assignment, a binary
expression, a local and a return are all on screen at once.

Generated C#:

    public class Counter
    {
        int count = 0;
        int step = 1;
        public int Add(int amount)
        {
            count = (count + amount);
            return count;
        }
        public int Next()
        {
            int result = (count + step);
            return result;
        }
    }

Doing this surfaced a bug that made the new document unopenable, and would
have hit any document with an assignment in it. AssignmentStatement's
parameterless constructor - the one its own comment says is for
deserialization - built its placeholder target with
`new VariableReference("")`, and that overload throws on an empty name. So
YamlDeserializer threw before it could overwrite the placeholder, and the
load failed. It now uses the parameterless VariableReference, whose whole
job is to leave the name empty.

NewClassDocument is left alone: "New class" still gives a bare class to
start from, which is a different thing from a worked example.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D2KNUKr1xJPTEdDmeF2tQN
Comment thread Coder.Test/Editor/CoderEditorAppTests.cs Fixed
…ture

The fixture's `root` is the temporary directory the store writes into, so a
local of the same name holding the reopened document's root node read as
the same thing twice over. Now `reopenedRoot`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D2KNUKr1xJPTEdDmeF2tQN
@sonarqubecloud

sonarqubecloud Bot commented Sep 8, 2026

Copy link
Copy Markdown

@matt-edmondson
matt-edmondson merged commit cc2ba91 into main Sep 8, 2026
12 checks passed
@matt-edmondson
matt-edmondson deleted the claude/default-document-class branch September 8, 2026 09:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants